package com.xbongbong.paas.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.help.condition.ConditionHelper;
import com.xbongbong.i18n.util.I18nMessageUtil;
import com.xbongbong.paas.constant.MessageConstant;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.enums.ConditionEnum;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.OptionalRangeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.help.CommonHelp;
import com.xbongbong.paas.log.MongoLogHelp;
import com.xbongbong.paas.log.constant.LogMemoConstant;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.pojo.ClueAutoAllocationDetailPojo;
import com.xbongbong.paas.pojo.ClueAutoAllocationPojo;
import com.xbongbong.paas.pojo.dto.ClueAutoAllocationDetailDTO;
import com.xbongbong.paas.pojo.dto.ClueAutoAllocationListSortDTO;
import com.xbongbong.paas.pojo.dto.ClueAutoAllocationSaveDTO;
import com.xbongbong.paas.pojo.vo.ClueAutoAllocationDetailVO;
import com.xbongbong.paas.pojo.vo.ClueAutoAllocationListVO;
import com.xbongbong.paas.service.AutomaticallyAssignedService;
import com.xbongbong.paas.service.TemplateService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.RegexUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.BaseDTO;
import com.xbongbong.paas.toolbox.wrap.BaseVO;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.constant.I18nStringConstant;
import com.xbongbong.pro.domain.entity.LabelEntity;
import com.xbongbong.pro.domain.entity.PriorityUpdateEntity;
import com.xbongbong.pro.enums.ErrorCodeEnum;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.errorcodes.ClueErrorCodeEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.template.pojo.EnablePojo;
import com.xbongbong.pro.template.pojo.dto.TemplateDTO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.ClueAutoAllocationEntity;
import com.xbongbong.saas.enums.ClueAutoDistributTypeEnum;
import com.xbongbong.saas.enums.CompanyConfigEnum;
import com.xbongbong.saas.enums.OperateModuleTypeEnum;
import com.xbongbong.saas.enums.OperateTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.ClueEnum;
import com.xbongbong.saas.model.ClueAutoAllocationModel;
import com.xbongbong.saas.model.LabelModel;
import com.xbongbong.sys.domain.entity.CompanyConfigEntity;
import com.xbongbong.sys.domain.entity.DepartmentEntity;
import com.xbongbong.sys.domain.entity.UserEntity;
import com.xbongbong.sys.model.CompanyConfigModel;
import com.xbongbong.sys.model.DepartmentModel;
import com.xbongbong.sys.model.UserModel;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import static com.xbongbong.saas.enums.ClueAutoDistributTypeEnum.PROPORTIONAL_ALLOCATION;

/**
 * @author long
 * @version v1.0
 * @date 2021/1/15 11:05
 * @since v1.0
 */
@Service("automaticallyAssignedService")
public class AutomaticallyAssignedServiceImpl implements AutomaticallyAssignedService {

    private static final Logger LOG = LoggerFactory.getLogger(AutomaticallyAssignedServiceImpl.class);


    @Resource
    private ClueAutoAllocationModel clueAutoAllocationModel;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private UserModel userModel;
    @Resource
    private LabelModel labelModel;
    @Resource
    private MongoLogHelp mongoLogHelp;
    @Resource
    private DepartmentModel departmentModel;
    @Resource
    private CompanyConfigModel companyConfigModel;
    @Resource
    private TemplateService templateService;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private CommonHelp commonHelp;

    @Resource
    private ConditionHelper conditionHelper;

    @Override
    public ClueAutoAllocationListVO distributionList(BaseDTO baseDTO) throws XbbException {
        String corpid = baseDTO.getCorpid();
        boolean isPublicSeniorMode = commonHelp.isCluePublicPoolSeniorModel(corpid);
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        String configAlias = CompanyConfigEnum.AUTOMATICALLY_ASSIGNED.getAlias();
        param.put("modelType", BasicConstant.ONE);
        if (isPublicSeniorMode){
            param.put("modelType", BasicConstant.TWO);
            configAlias = CompanyConfigEnum.AUTOMATICALLY_ASSIGNED_SENIOR.getAlias();
        }
        param.put(ParameterConstant.CORPID, corpid);
        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        param.put("orderByStr", "priority asc");
        List<ClueAutoAllocationEntity> entitys = clueAutoAllocationModel.findEntitys(param);
        Map<String, Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        map.put("corpid", corpid);
        map.put("del", DelEnum.NORMAL.getDel());
        map.put("businessType", XbbRefTypeEnum.CLUE.getCode());
        List<PaasFormEntityExt> formEntityExts = paasFormModel.findEntitys(map);
        Map<Long, String> formIdAndName = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (PaasFormEntityExt entity : formEntityExts) {
            formIdAndName.put(entity.getId(), entity.getName());
        }

        List<ClueAutoAllocationPojo> clueAutoAllocationPojos = new ArrayList<>();
        for (ClueAutoAllocationEntity entity : entitys) {
            ClueAutoAllocationPojo pojo = new ClueAutoAllocationPojo();
            pojo.setId(entity.getId());
            pojo.setRuleName(entity.getRuleName());
            pojo.setFormName(formIdAndName.getOrDefault(entity.getFormId(), ""));
            pojo.setJsonData(entity.getJsonData());
            pojo.setAllocationTypeStr(ClueAutoDistributTypeEnum.getNameByCode(entity.getAllocationType()));
            JSONArray jsonArray = entity.getJsonData();
            if (!jsonArray.isEmpty()) {
                // 处理有员工的筛选条件
                conditionHelper.handleUserConditions(corpid,jsonArray);
            }


            clueAutoAllocationPojos.add(pojo);
        }
        ClueAutoAllocationListVO clueAutoAllocationListVO = new ClueAutoAllocationListVO();
        clueAutoAllocationListVO.setClueAutoAllocationPojos(clueAutoAllocationPojos);

        CompanyConfigEntity configEntity = companyConfigModel.getByConfigAlias(configAlias, corpid);
        if (Objects.nonNull(configEntity) && Objects.equals(configEntity.getConfigValue(), "1")) {
            clueAutoAllocationListVO.setStatus(1);
        } else {
            clueAutoAllocationListVO.setStatus(0);
        }

        TemplateDTO templateDTO = new TemplateDTO();
        BeanUtil.copyProperties(baseDTO, templateDTO);
        templateDTO.setSubBusinessType(XbbRefTypeEnum.CLUE.getCode());
        templateDTO.setSaasMark(SaasMarkEnum.SAAS.getCode());
        List<EnablePojo> saasTemplateList = templateService.getSaasTemplateList(templateDTO);
        clueAutoAllocationListVO.setFormList(saasTemplateList);
        CompanyConfigEntity companyConfigEntity = companyConfigModel.getByConfigAlias(CompanyConfigEnum.AUTOMATICALLY_ASSIGNED_NUM.getAlias(), corpid);
        if (Objects.nonNull(companyConfigEntity)) {
            clueAutoAllocationListVO.setNum(Integer.valueOf(companyConfigEntity.getConfigValue()));
        } else {
            clueAutoAllocationListVO.setNum(Integer.valueOf(CompanyConfigEnum.AUTOMATICALLY_ASSIGNED_NUM.getValue()));
        }
        return clueAutoAllocationListVO;
    }



    @Override
    public BaseVO distributionSort(ClueAutoAllocationListSortDTO clueAutoAllocationListSortDTO) throws XbbException{
        BaseVO baseVO = new BaseVO();
        List<Long> ids = clueAutoAllocationListSortDTO.getIds();
        String corpid = clueAutoAllocationListSortDTO.getCorpid();
        boolean publicPoolSeniorModel = commonHelp.isCluePublicPoolSeniorModel(corpid);
        CompanyConfigEnum companyConfigEnum = CompanyConfigEnum.AUTOMATICALLY_ASSIGNED;
        if (publicPoolSeniorModel){
            companyConfigEnum = CompanyConfigEnum.AUTOMATICALLY_ASSIGNED_SENIOR;
        }

        if (CollectionsUtil.isNotEmpty(ids)) {
            List<PriorityUpdateEntity> priorityUpdateEntities = new ArrayList<>();
            for (int i=0;i<ids.size();i++) {
                PriorityUpdateEntity entity = new PriorityUpdateEntity();
                entity.setId(ids.get(i));
                entity.setPriority(i);
                priorityUpdateEntities.add(entity);
            }
            clueAutoAllocationModel.sort(priorityUpdateEntities, corpid);
        }

        Integer status = clueAutoAllocationListSortDTO.getStatus();

        CompanyConfigEntity configEntity = companyConfigModel.getByConfigAlias(companyConfigEnum.getAlias(), corpid);
        Long now = DateTimeUtil.getInt();
        if (Objects.isNull(configEntity)) {
            configEntity = new CompanyConfigEntity();
            configEntity.setAddTime(now);
            configEntity.setConfigAlias(companyConfigEnum.getAlias());
            configEntity.setConfigName(companyConfigEnum.getName());
            configEntity.setCorpid(corpid);
            configEntity.setDel(DelEnum.NORMAL.getDel());
        }
        configEntity.setUpdateTime(now);
        configEntity.setConfigValue(status.toString());
        try {
            companyConfigModel.save(configEntity);
            distributionStatusUpdateMemo(configEntity, clueAutoAllocationListSortDTO);
        } catch (XbbException e) {
            LOG.error("AutomaticallyAssignedServiceImpl.distributionSort保存配置并且日志保存错误", e);
        }
        return baseVO;
    }

    @Override
    public ClueAutoAllocationDetailVO distributionDetail(ClueAutoAllocationDetailDTO clueAutoAllocationDetailDTO) throws XbbException {
        ClueAutoAllocationDetailVO clueAutoAllocationDetailVO = new ClueAutoAllocationDetailVO();

        Long id = clueAutoAllocationDetailDTO.getId();
        String corpid = clueAutoAllocationDetailDTO.getCorpid();
        ClueAutoAllocationEntity ruleEntity = clueAutoAllocationModel.getByKey(id, corpid);
        if (Objects.isNull(ruleEntity)) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100404);
        }

        Long formId = ruleEntity.getFormId();

        PaasFormEntityExt formEntity = paasFormModel.getByKey(formId, corpid);

        ClueAutoAllocationDetailPojo pojo = new ClueAutoAllocationDetailPojo();
        BeanUtil.copyProperties(ruleEntity, pojo);
        JSONArray jsonData = ruleEntity.getJsonData();
        if (!jsonData.isEmpty()) {
            // 处理有员工的筛选条件
            conditionHelper.handleUserConditions(corpid, jsonData);
            pojo.setJsonData(jsonData);
        }
        if (Objects.nonNull(formEntity)) {
            pojo.setFormName(formEntity.getName());
        }
        JSONArray allocationValue = ruleEntity.getAllocationValue();
        if (!allocationValue.isEmpty()) {
            // 处理有员工或部门的筛选条件
            formatAllocationValue(corpid, allocationValue, ruleEntity.getAllocationType());
            pojo.setAllocationValue(allocationValue);
        }
        clueAutoAllocationDetailVO.setClueAutoAllocation(pojo);
        return clueAutoAllocationDetailVO;
    }

    @Override
    public BaseVO distributionSave(ClueAutoAllocationSaveDTO clueAutoAllocationSaveDTO) throws XbbException {
        ClueAutoAllocationEntity clueAutoAllocationEntity = new ClueAutoAllocationEntity();

        Long id = clueAutoAllocationSaveDTO.getId();
        Long now = DateTimeUtil.getInt();
        String corpid = clueAutoAllocationSaveDTO.getCorpid();
        boolean publicPoolSeniorModel = commonHelp.isCluePublicPoolSeniorModel(corpid);
        Integer modelType = BasicConstant.ONE;
        if (publicPoolSeniorModel){
            modelType = BasicConstant.TWO;
        }
        // 校验参数
        verifyParam(clueAutoAllocationSaveDTO,modelType);
        if (Objects.isNull(id)) {
            clueAutoAllocationEntity.setAddTime(now);
            clueAutoAllocationEntity.setUpdateTime(now);
            clueAutoAllocationEntity.setDel(0);
            clueAutoAllocationEntity.setModelType(modelType);
        } else {
            clueAutoAllocationEntity = clueAutoAllocationModel.getByKey(id, clueAutoAllocationSaveDTO.getCorpid());
            if (Objects.isNull(clueAutoAllocationEntity)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100404);
            }
            clueAutoAllocationEntity.setModelType(modelType);
            clueAutoAllocationSaveDTO.setPriority(null);
            clueAutoAllocationEntity.setUpdateTime(now);
        }

        // 线索自动分配规则日志
        String userId = clueAutoAllocationSaveDTO.getUserId();
        Long formId = clueAutoAllocationSaveDTO.getFormId();
        // 登录用户
        String loginUserName = clueAutoAllocationSaveDTO.getLoginUserName();
        // 规则名称
        String opObjectName = clueAutoAllocationSaveDTO.getRuleName();
        // 关联表单模版
        String newFormName = null;
        String oldFormName = null;
        if (Objects.isNull(id)) {
            newFormName = formName(formId, corpid);
        } else {
            if(!Objects.equals(clueAutoAllocationEntity.getFormId(), formId)){
                newFormName = formName(formId, corpid);
                oldFormName = formName(clueAutoAllocationEntity.getFormId(), corpid);
            }
        }
        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByFormId(formId,corpid);
        Map<String, FieldAttrEntity> explainMap = null;
        if ( Objects.nonNull(paasFormExplainEntity)){
            explainMap = ExplainUtil.getExplainMap(paasFormExplainEntity.getExplains());
        }
        // 筛选条件
        String newConditionStr = null;
        String oldConditionStr = null;
        JSONArray jsonData = clueAutoAllocationSaveDTO.getJsonData();
        JSONArray arr = JSONArray.parseArray(jsonData.toJSONString());
        if (Objects.isNull(id)) {
            newConditionStr = condition(explainMap, arr, corpid);
        } else {
            JSONArray oldJsonData = clueAutoAllocationEntity.getJsonData();
            JSONArray oldArr = JSONArray.parseArray(oldJsonData.toJSONString());
            if(!Objects.equals(oldArr, arr)){
                newConditionStr = condition(explainMap, arr, corpid);
                oldConditionStr = condition(explainMap, oldArr, corpid);
            }
        }

        // 分配上限(是否遵循最大拥有线索数规则)
        Integer newDistributionLimit = null;
        Integer oldDistributionLimit = null;
        if (Objects.isNull(id)) {
            newDistributionLimit = clueAutoAllocationSaveDTO.getDistributionLimit() == null ? BasicConstant.ZERO : clueAutoAllocationSaveDTO.getDistributionLimit();
        } else {
            oldDistributionLimit = clueAutoAllocationEntity.getDistributionLimit() == null ? BasicConstant.ZERO : clueAutoAllocationEntity.getDistributionLimit();
            if(!Objects.equals(oldDistributionLimit, newDistributionLimit)){
                newDistributionLimit = clueAutoAllocationSaveDTO.getDistributionLimit() == null ? BasicConstant.ZERO : clueAutoAllocationSaveDTO.getDistributionLimit();
                oldDistributionLimit = clueAutoAllocationEntity.getDistributionLimit() == null ? BasicConstant.ZERO : clueAutoAllocationEntity.getDistributionLimit();
            }
        }
        String newDistributionLimitStr = Objects.equals(newDistributionLimit, BasicConstant.ZERO) ? I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_NOT_FOLLOW_MAX_NUMBER_AUTO_DISTRIBUTION_RULE) : I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_FOLLOW_MAX_NUMBER_AUTO_DISTRIBUTION_RULE);
        String oldDistributionLimitStr = Objects.equals(oldDistributionLimit, BasicConstant.ZERO) ? I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_NOT_FOLLOW_MAX_NUMBER_AUTO_DISTRIBUTION_RULE) : I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_FOLLOW_MAX_NUMBER_AUTO_DISTRIBUTION_RULE);

        // 分配间隔
        String newAllocationIntervalStr = null;
        String oldAllocationIntervalStr = null;
        Integer newAllocationInterval = clueAutoAllocationSaveDTO.getAllocationInterval();
        // 分配完成后，隔N天再次分配
        if (Objects.isNull(id)) {
            newAllocationIntervalStr = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_INTERVAL_AUTO_DISTRIBUTION_RULE), newAllocationInterval);
        } else {
            Integer oldAllocationInterval = clueAutoAllocationEntity.getAllocationInterval();
            if(!Objects.equals(oldAllocationInterval, newAllocationInterval)){
                newAllocationIntervalStr = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_INTERVAL_AUTO_DISTRIBUTION_RULE), newAllocationInterval);
                oldAllocationIntervalStr = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_INTERVAL_AUTO_DISTRIBUTION_RULE), oldAllocationInterval);
            }
        }

        // 分配类型
        String newAutoTypeNameStr = null;
        String oldAutoTypeNameStr = null;
        Integer newAllocationType = clueAutoAllocationSaveDTO.getAllocationType();
        String newAutoTypeName = ClueAutoDistributTypeEnum.getNameByCode(newAllocationType);
        if (Objects.isNull(id)) {
            newAutoTypeNameStr = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_TYPE_AUTO_DISTRIBUTION_RULE), newAutoTypeName);
        } else {
            Integer oldAllocationType = clueAutoAllocationEntity.getAllocationType();
            String oldAutoTypeName = ClueAutoDistributTypeEnum.getNameByCode(oldAllocationType);
            if(!Objects.equals(oldAllocationType, newAllocationType)){
                newAutoTypeNameStr = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_TYPE_AUTO_DISTRIBUTION_RULE), newAutoTypeName);
                oldAutoTypeNameStr = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_TYPE_AUTO_DISTRIBUTION_RULE), oldAutoTypeName);
            }
        }

        // 人员处理
        String newUserChoose = null;
        String oldUserChoose = null;
        JSONArray newAllocationValue = clueAutoAllocationSaveDTO.getAllocationValue();
        if (Objects.isNull(id)) {
            newUserChoose = user4Distribution(corpid, newAllocationType, newAllocationValue);
        } else {
            JSONArray oldAllocationValue = clueAutoAllocationEntity.getAllocationValue();
            Integer oldAllocationType = clueAutoAllocationEntity.getAllocationType();
            if(!Objects.equals(oldAllocationType, newAllocationType) || !Objects.equals(oldAllocationValue, newAllocationValue)){
                newUserChoose = user4Distribution(corpid, newAllocationType, newAllocationValue);
                oldUserChoose = user4Distribution(corpid, oldAllocationType, oldAllocationValue);
            }
        }

        String defaultMemo = "";
        if(Objects.isNull(id)){
            defaultMemo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_ADD_CLUE_AUTO_DISTRIBUTION_RULE), loginUserName, opObjectName);
        } else {
            defaultMemo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_CLUE_AUTO_DISTRIBUTION_RULE), loginUserName, opObjectName);
        }
        StringBuilder memoStr = new StringBuilder();
        memoStr.append(defaultMemo);

        OperateTypeEnum operateTypeEnum;
        if(Objects.isNull(id)){
            if(newFormName != null){
                String formStr = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_ASSOCIATED_FORM_TEMPLATE_AUTO_DISTRIBUTION_RULE), newFormName);
                memoStr.append(formStr);
            }
            if(newConditionStr != null){
                memoStr.append(newConditionStr);
            }
            memoStr.append(newDistributionLimitStr);
            if(newAllocationIntervalStr != null){
                memoStr.append(newAllocationIntervalStr);
            }
            if(newAutoTypeNameStr != null){
                memoStr.append(newAutoTypeNameStr);
            }
            if(newUserChoose != null){
                memoStr.append(newUserChoose);
            }
            operateTypeEnum = OperateTypeEnum.NEW;
        } else {
            if(!Objects.equals(oldFormName, newFormName)){
                String oldFormStr = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_ASSOCIATED_FORM_TEMPLATE_AUTO_DISTRIBUTION_RULE), oldFormName);
                String newFormStr = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_ASSOCIATED_FORM_TEMPLATE_AUTO_DISTRIBUTION_RULE), newFormName);
                String changeForm = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_CHANGE_USER_AUTO_DISTRIBUTION_RULE), oldFormStr, newFormStr);
                memoStr.append(changeForm);
            }
            if(!Objects.equals(oldConditionStr, newConditionStr)){
                String changeCondition = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_CHANGE_USER_AUTO_DISTRIBUTION_RULE), oldConditionStr, newConditionStr);
                memoStr.append(changeCondition);
            }
            if(!Objects.equals(oldDistributionLimitStr, newDistributionLimitStr)){
                String changeDistribution = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_CHANGE_USER_AUTO_DISTRIBUTION_RULE), oldDistributionLimitStr, newDistributionLimitStr);
                memoStr.append(changeDistribution);
            }
            if(!Objects.equals(oldAllocationIntervalStr, newAllocationIntervalStr)){
                String changeInterval = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_CHANGE_USER_AUTO_DISTRIBUTION_RULE), oldAllocationIntervalStr, newAllocationIntervalStr);
                memoStr.append(changeInterval);
            }
            if(!Objects.equals(oldAutoTypeNameStr, newAutoTypeNameStr)){
                String changeAutoType = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_CHANGE_USER_AUTO_DISTRIBUTION_RULE), oldAutoTypeNameStr, newAutoTypeNameStr);
                memoStr.append(changeAutoType);
            }
            if(!Objects.equals(oldUserChoose, newUserChoose)){
                String changeUserChoose = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_CHANGE_USER_AUTO_DISTRIBUTION_RULE), oldUserChoose, newUserChoose);
                memoStr.append(changeUserChoose);
            }
            operateTypeEnum = OperateTypeEnum.EDIT;
        }

        BeanUtil.copyProperties(clueAutoAllocationSaveDTO, clueAutoAllocationEntity, true);
        clueAutoAllocationModel.save(clueAutoAllocationEntity);

        mongoLogHelp.buildLog(corpid, userId, loginUserName, OperateModuleTypeEnum.OpenSeaRules, operateTypeEnum,
                clueAutoAllocationEntity.getId().toString(), OperateModuleTypeEnum.OpenSeaRules.getName(), memoStr.toString(), clueAutoAllocationSaveDTO.getHttpHeader());


        return new BaseVO();
    }

    private void verifyParam(ClueAutoAllocationSaveDTO clueAutoAllocationSaveDTO,Integer modelType) throws XbbException{
        try {

            PaasFormEntityExt formEntity = paasFormModel.getByKey(clueAutoAllocationSaveDTO.getFormId(), clueAutoAllocationSaveDTO.getCorpid());
            if (Objects.isNull(formEntity)) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_NOT_EXIST);
            }
            String ruleName = clueAutoAllocationSaveDTO.getRuleName();
            if (ruleName.length() > 20) {
                throw new XbbException(ClueErrorCodeEnum.API_ERROR_1111007);
            }
            String corpid = clueAutoAllocationSaveDTO.getCorpid();
            CompanyConfigEntity companyConfigEntity = companyConfigModel.getByConfigAlias(CompanyConfigEnum.AUTOMATICALLY_ASSIGNED_NUM.getAlias(), corpid);
            Integer maxNum = Integer.valueOf(CompanyConfigEnum.AUTOMATICALLY_ASSIGNED_NUM.getValue());
            if (Objects.nonNull(companyConfigEntity)) {
                maxNum = Integer.valueOf(companyConfigEntity.getConfigValue());
            }
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put(StringConstant.CORPID, corpid);
            param.put("del", DelEnum.NORMAL.getDel());
            param.put("modelType",modelType);
            Integer count = clueAutoAllocationModel.getEntitysCount(param);
            if (count >= maxNum) {
                throw new XbbException(ClueErrorCodeEnum.API_ERROR_1111009, String.format(ClueErrorCodeEnum.API_ERROR_1111009.getMsg(), maxNum));
            }
            param.clear();
            param.put("corpid", corpid);
            param.put("del", DelEnum.NORMAL.getDel());
            param.put("ruleName", ruleName);
            param.put("modelType",modelType);
            if (Objects.nonNull(clueAutoAllocationSaveDTO.getId())) {
                param.put("idNot", clueAutoAllocationSaveDTO.getId());
            }
            List<ClueAutoAllocationEntity> entitys = clueAutoAllocationModel.findEntitys(param);
            if (CollectionsUtil.isNotEmpty(entitys)) {
                throw new XbbException(ClueErrorCodeEnum.API_ERROR_1111008);
            }

            JSONArray jsonData = clueAutoAllocationSaveDTO.getJsonData();
            if (jsonData.isEmpty()) {
                throw new XbbException(ClueErrorCodeEnum.API_ERROR_1111003);
            }
            // 这边转一下，因为前端传过来的时候这边还是个linkhashmap，强转JSONObject会报错
            JSONArray arr = JSONArray.parseArray(jsonData.toJSONString());
            for (Object o : arr) {
                JSONObject object = (JSONObject) o;
                String symbol = object.getString("symbol");
                if (StringUtil.isEmpty(symbol)) {
                    throw new XbbException(ClueErrorCodeEnum.API_ERROR_1111003);
                }
                String attr = object.getString("attr");
                if (StringUtil.isEmpty(attr)) {
                    throw new XbbException(ClueErrorCodeEnum.API_ERROR_1111003);
                }

                JSONArray value = object.getJSONArray("value");
                if (!(Objects.equals(symbol, ConditionEnum.EMPTY.getSymbol()) || Objects.equals(symbol, ConditionEnum.NOEMPTY.getSymbol())) && (Objects.isNull(value) || value.isEmpty() || StringUtil.isEmpty(value.getString(0), true))) {
                    // 除了为空或不为空，其它的条件的value都不能空
                    throw new XbbException(ClueErrorCodeEnum.API_ERROR_1111003);
                }
            }

            Integer allocationInterval = clueAutoAllocationSaveDTO.getAllocationInterval();
            if (!Objects.equals(allocationInterval, 0) && !RegexUtil.isInteger(allocationInterval.toString())) {
                throw new XbbException(ClueErrorCodeEnum.API_ERROR_1111006);
            }

            JSONArray allocationValue = clueAutoAllocationSaveDTO.getAllocationValue();
            if (allocationValue.isEmpty()) {
                throw new XbbException(ClueErrorCodeEnum.API_ERROR_1111004);
            }

            Integer allocationType = clueAutoAllocationSaveDTO.getAllocationType();
            // 这边转一下，因为前端传过来的时候这边还是个linkhashmap，强转JSONObject会报错
            JSONArray valueArr = JSONArray.parseArray(allocationValue.toJSONString());
            for (Object o : valueArr) {
                JSONObject object = (JSONObject) o;
                String usersStr = object.getString("user");
                List<String> userIds = JSONArray.parseArray(usersStr, String.class);
                Integer num = object.getInteger("num");
                if (CollectionsUtil.isEmpty(userIds)) {
                    throw new XbbException(ClueErrorCodeEnum.API_ERROR_1111004);
                }
                if (Objects.equals(allocationType, PROPORTIONAL_ALLOCATION.getType()) || Objects.equals(allocationType, ClueAutoDistributTypeEnum.NUMBER_ASSIGNED.getType())) {
                    if (Objects.isNull(num)) {
                        throw new XbbException(ClueErrorCodeEnum.API_ERROR_1111004);
                    }
                    boolean number = RegexUtil.isInteger(object.getString("num"));
                    if (!number || num < 1) {
                        throw new XbbException(ClueErrorCodeEnum.API_ERROR_1111005);
                    }
                }
            }
            if (Objects.equals(allocationType, PROPORTIONAL_ALLOCATION.getType())) {
                if (!Objects.equals(valueArr.size(), 2)) {
                    throw new XbbException(ClueErrorCodeEnum.API_ERROR_1111004);
                }

            }
        } catch (XbbException e) {
            throw e;
        } catch (Exception e) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100015);
        }
    }

    /**
     * 获取关联表单模版
     * @param
     * @return
     * @throws XbbException
     */
    private String formName(Long formId, String corpid) throws XbbException{
        String formName = null;
        if(formId != null){
            PaasFormEntityExt paasFormEntityExt = paasFormModel.getByKey(formId, corpid);
            if (paasFormEntityExt == null) {
                throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, MessageConstant.FORM_DATA_NOT_EXIST);
            }
            formName = paasFormEntityExt.getName();
        }
        return formName;
    }

    /**
     * 筛选条件
     * @param explainMap
     * @param corpid
     * @param arr
     * @return
     * @throws XbbException
     */
    private String condition(Map<String, FieldAttrEntity> explainMap, JSONArray arr, String corpid) throws XbbException{
        // 符号
        String mark = "";
        // 字段
        String attrName = "";
        // 数据
        String data = "";

        StringBuilder conditionStr = new StringBuilder();
        String memo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_CONDITION_AUTO_DISTRIBUTION_RULE));
        conditionStr.append(memo);
        for (Object o : arr) {
            JSONObject object = (JSONObject) o;
            String symbol = object.getString("symbol");
            Integer fieldType = object.getInteger("fieldType");
            ConditionEnum conditionEnum = ConditionEnum.getConditionEnum(symbol);
            if(conditionEnum != null){
                mark = conditionEnum.getMemo();
            }
            String attr = object.getString("attr");
            FieldAttrEntity fieldAttrEntity = null ;
            if ( !explainMap.isEmpty() ){
                fieldAttrEntity =explainMap.get(attr);
            }
            attrName = Objects.nonNull(fieldAttrEntity) ? fieldAttrEntity.getAttrName() : null;
            JSONArray value = object.getJSONArray("value");
            try{
                List<String> dataArr = JSONArray.parseArray(JSON.toJSONString(value),String.class);

                List<String> nameIn = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                if(Objects.equals(attr, ClueEnum.OWNER_ID.getAttr()) || Objects.equals(attr, ClueEnum.CREATOR_ID.getAttr()) || Objects.equals(fieldType, FieldTypeEnum.USER.getType()) || Objects.equals(fieldType, FieldTypeEnum.USER_GROUP.getType())){
                    if(CollectionUtils.isNotEmpty(dataArr)){
                        List<UserEntity> getByUserId = userModel.getByUserId(dataArr,corpid);
                        getByUserId.forEach(userEntity -> nameIn.add(userEntity.getName()));
                    }
                    data = StringUtils.join(nameIn, "，");
                } else if(Objects.equals(attr, ClueEnum.LABEL.getAttr())){
                    List<Long> labelIdIn = JSONArray.parseArray(JSON.toJSONString(value),Long.class);
                    if(CollectionUtils.isNotEmpty(labelIdIn)){
                        List<LabelEntity> getByLabelIds = labelModel.getByLabelIds(labelIdIn,corpid);
                        getByLabelIds.forEach(labelEntity -> nameIn.add(labelEntity.getName()));
                    }
                    data = StringUtils.join(nameIn, "，");
                } else if (Objects.equals(fieldType, FieldTypeEnum.ADDTIME.getType()) || Objects.equals(fieldType, FieldTypeEnum.UPDATETIME.getType()) || Objects.equals(fieldType, FieldTypeEnum.DATETIME.getType())){
                    List<Long> timeIn = JSONArray.parseArray(JSON.toJSONString(value),Long.class);
                    if(CollectionUtils.isNotEmpty(timeIn)){
                        for(Long time : timeIn){
                            String timeStr = DateTimeUtil.getStringEpochSecond(time, DateTimeUtil.SDFDate);
                            nameIn.add(timeStr);
                        }
                    }
                    data = StringUtils.join(nameIn, "，");
                } else {
                    data = StringUtils.join(dataArr, "，");
                }

            } catch (Exception e) {
                data = "";
            }
            if(attrName != null){
                if(data != null){
                    conditionStr.append(attrName).append(mark).append(data).append(";");
                } else {
                    conditionStr.append(attrName).append(mark).append(";");
                }
            } else {
                conditionStr.append(mark).append(data).append(";");
            }
        }
        return conditionStr.toString();
    }

    /**
     * 人员分配
     * @param corpid
     * @param allocationType
     * @param allocationValue
     * @return
     * @throws XbbException
     */
    private String user4Distribution(String corpid, Integer allocationType, JSONArray allocationValue) throws XbbException{
        List<String> onlyUserIdList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);

        List<List<String>> userIdList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<Integer> numList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);

        JSONArray valueArr = JSONArray.parseArray(allocationValue.toJSONString());
        for (Object o : valueArr) {
            JSONObject object = (JSONObject) o;
            String usersStr = object.getString("user");
            List<String> userIds = JSONArray.parseArray(usersStr, String.class);
            Integer num = object.getInteger("num");
            if (CollectionsUtil.isEmpty(userIds)) {
                continue;
            }
            if(Objects.equals(allocationType, ClueAutoDistributTypeEnum.ONLY_ASSIGNED.getType()) || Objects.equals(allocationType, ClueAutoDistributTypeEnum.CIRCULATION_DISTRIBUTION.getType())) {
                onlyUserIdList.addAll(userIds);
            }
            if (Objects.equals(allocationType, ClueAutoDistributTypeEnum.PROPORTIONAL_ALLOCATION.getType()) || Objects.equals(allocationType, ClueAutoDistributTypeEnum.NUMBER_ASSIGNED.getType())) {
                if (Objects.isNull(num)) {
                    continue;
                }
                boolean number = RegexUtil.isInteger(object.getString("num"));
                if (!number || num < 1) {
                    continue;
                }
                List<String> user = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                user.addAll(userIds);
                userIdList.add(user);

                numList.add(num);
            }
        }

        StringBuilder user4Distribution = new StringBuilder();
        if(Objects.equals(allocationType, ClueAutoDistributTypeEnum.ONLY_ASSIGNED.getType()) || Objects.equals(allocationType, ClueAutoDistributTypeEnum.CIRCULATION_DISTRIBUTION.getType())) {
            List<UserEntity> userList = userModel.getByUserId(onlyUserIdList, corpid);
            List<String> onlyUserName = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            userList.forEach(userEntity -> onlyUserName.add(userEntity.getName()));
            String nameStr = StringUtils.join(onlyUserName, "，");
            String onlyMemo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_CHOOSE_USER_AUTO_DISTRIBUTION_RULE), nameStr);
            user4Distribution.append(onlyMemo);
        }
        if (Objects.equals(allocationType, ClueAutoDistributTypeEnum.PROPORTIONAL_ALLOCATION.getType()) || Objects.equals(allocationType, ClueAutoDistributTypeEnum.NUMBER_ASSIGNED.getType())) {
            List<String> userNames = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for(List<String> userIdIn : userIdList){
                List<UserEntity> userList = userModel.getByUserId(userIdIn, corpid);
                List<String> onlyUserName = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                userList.forEach(userEntity -> onlyUserName.add(userEntity.getName()));
                String nameStr = StringUtils.join(onlyUserName, "，");
                userNames.add(nameStr);
            }
            for(String name : userNames){
                String nameMemo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_CHOOSE_USER_AUTO_DISTRIBUTION_RULE), name);
                user4Distribution.append(nameMemo);
            }
            List<String> numStr = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for(Integer num : numList){
                numStr.add(String.valueOf(num));
            }
            if (Objects.equals(allocationType, ClueAutoDistributTypeEnum.PROPORTIONAL_ALLOCATION.getType())){
                String numStrMemo = StringUtils.join(numStr, ":");
                String numMemo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_CHOOSE_SCALE_USER_AUTO_DISTRIBUTION_RULE), numStrMemo);
                user4Distribution.append(numMemo);
            }
            if (Objects.equals(allocationType, ClueAutoDistributTypeEnum.NUMBER_ASSIGNED.getType())){
                String numStrMemo = StringUtils.join(numStr, "；");
                String numMemo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_CHOOSE_NUM_USER_AUTO_DISTRIBUTION_RULE), numStrMemo);
                user4Distribution.append(numMemo);
            }
        }
        return user4Distribution.toString();
    }

    private void distributionStatusUpdateMemo(CompanyConfigEntity configEntity, ClueAutoAllocationListSortDTO clueAutoAllocationListSortDTO) throws XbbException {
        String userId = clueAutoAllocationListSortDTO.getUserId();
        String corpid = clueAutoAllocationListSortDTO.getCorpid();
        // 登录用户
        String loginUserName = clueAutoAllocationListSortDTO.getLoginUserName();
        Integer status = clueAutoAllocationListSortDTO.getStatus();
        // 公海池规则名称
        String opObjectName = CompanyConfigEnum.AUTOMATICALLY_ASSIGNED.getName();
        String defaultMemo = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_UPDATE_CLUE_RULE), loginUserName, opObjectName);

        OperateTypeEnum operateTypeEnum;
        // 是否启用或关闭某种规则
        String isOpenRule = null;
        if (Objects.equals(status, 0)) {
            if (Objects.isNull(configEntity) || Objects.equals(configEntity, "0")) {
                // 如果没有修改状态，那么就不记录日志
                return;
            }
            operateTypeEnum = OperateTypeEnum.CLOSE;
            // 操作类型标识
            isOpenRule = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_CLOSE_CLUE_RULE), opObjectName);
        } else {
            if (Objects.nonNull(configEntity) || Objects.equals(configEntity, "1")) {
                // 如果没有修改状态，那么就不记录日志
                return;
            }
            operateTypeEnum = OperateTypeEnum.ENABLE;
            // 操作类型标识
            isOpenRule = String.format(I18nMessageUtil.getMessage(LogMemoConstant.LOG_MEMO_USER_OPEN_CLUE_RULE), opObjectName);
        }

        StringBuilder memoStr = new StringBuilder();
        memoStr.append(defaultMemo).append(isOpenRule);


        mongoLogHelp.buildLog(corpid, userId, loginUserName, OperateModuleTypeEnum.OpenSeaRules, operateTypeEnum,
                "", OperateModuleTypeEnum.OpenSeaRules.getName(), memoStr.toString(), clueAutoAllocationListSortDTO.getHttpHeader());
    }

    @Override
    public BaseVO distributionDel(ClueAutoAllocationDetailDTO clueAutoAllocationDetailDTO) throws XbbException {
        try {
            clueAutoAllocationModel.deleteByKey(clueAutoAllocationDetailDTO.getId(), clueAutoAllocationDetailDTO.getCorpid());
        } catch (XbbException e) {
            LOG.error("distributionDel失败", e);
        }
        return new BaseVO();
    }

    private void formatAllocationValue(String corpid, JSONArray jsonArray, Integer allocationType) {
        Set<String> userIdIn = new HashSet<>();
        List<Long> depIdIn = new ArrayList<>();
        for(Object obj : jsonArray) {
            JSONObject conditionObj = (JSONObject) obj;
            List<Object> valueList;
            try {
                valueList = conditionObj.getJSONArray("user");
            } catch (JSONException e) {
                valueList = null;
            }
            if(Objects.isNull(valueList) || valueList.isEmpty()) {
                continue;
            }

            List<String> userIds = new ArrayList<>();
            for(Object userId: valueList) {
                userIds.add(userId.toString());
            }
            userIdIn.addAll(userIds);
        }
        // 查询部门或员工对应的数据
        List<UserEntity> userList;
        List<DepartmentEntity> deptList;
        Map<String, JSONObject> returnMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if(!userIdIn.isEmpty()) {
            userList = userModel.findEntitysByUserIds(new ArrayList<>(userIdIn), corpid);
            for(UserEntity userEntity : userList) {
                JSONObject object = new JSONObject();
                object.put("id", userEntity.getUserId());
                object.put("name", userEntity.getName());
                object.put("label", userEntity.getName());
                object.put("property", OptionalRangeEnum.USER.getValue());
                object.put("type", "user");
                object.put("value", userEntity.getUserId());
                returnMap.put(userEntity.getUserId(), object);
            }
        }

        for(Object obj : jsonArray) {
            JSONObject conditionObj = (JSONObject) obj;
            List<Object> valueList;
            try {
                valueList = conditionObj.getJSONArray("user");
            } catch (JSONException e) {
                valueList = null;
            }
            if(Objects.isNull(valueList) || valueList.isEmpty()) {
                continue;
            }
            //负责人变前负责人
            String attr = conditionObj.getString("attr");
            if (Objects.equals(attr,ClueEnum.OWNER_ID.getAttr())){
                conditionObj.put(StringConstant.SAAS_LINK_BUSINESS_NAME,I18nMessageUtil.getMessage(I18nStringConstant.PRE_OWNER_ID));
                conditionObj.put(StringConstant.LABEL,I18nMessageUtil.getMessage(I18nStringConstant.PRE_OWNER_ID));
            }
            JSONArray userArr = new JSONArray();
            for(Object userId: valueList) {
                String userIdStr = userId.toString();
                JSONObject jsonObject = returnMap.get(userIdStr);
                if (Objects.nonNull(jsonObject)) {
                    userArr.add(jsonObject);
                }
            }
            conditionObj.put("user", userArr);
        }

    }
}
